<?php 
/*\
 *	oh.array.include.php
 *	--------------------
 *
 *
 *
\*/

function oh_array_set($array,$path,$value) {
	if (is_array($path)) {
		switch (count($path)) {
			case 1: $array[$path[0]] = $value;break;
			case 2: $array[$path[0]][$path[1]] = $value;break;
			case 3: $array[$path[0]][$path[1]][$path[2]] = $value;break;
			case 4: $array[$path[0]][$path[1]][$path[2]][$path[3]] = $value;break;
		}
	}
	return $array;
}

function oh_array_get($array,$path) {
	if (is_array($path)) {
		switch (count($path)) {
			case 1: return $array[$path[0]];
			case 2: return $array[$path[0]][$path[1]];
			case 3: return $array[$path[0]][$path[1]][$path[2]];
			case 4: return $array[$path[0]][$path[1]][$path[2]][$path[3]];
		}
	}
	return null;
}

function aa_diff($a,$b,$d_a,$d_b,$debug=false) {
	$o = 0;
	for ($i=-19;$i<20;$i++) {
		if (isset($a[$i+$d_a])||isset($b[$i+$d_b])) {						
			if ($debug) echo '('.@$a[$i+$d_a].'):('.@$b[$i+$d_b].')';
			if (strlen(@$a[$i+$d_a])>0) {
				if (@$a[$i+$d_a] == @$b[$i+$d_b]) {
					$o++;				
					if ($debug) echo '*';	
				}
			}
			if ($debug) echo '<br>';
		}		
	}
	return $o;
}

function aa_delta($a,$b,$debug=false) {
	$o = -1000;
	$m = -1000;
	for ($i=-19;$i<20;$i++) {
		$t = aa_diff($a,$b,0,$i);
		if ($t>$m) {
			$o = $i;
			$m = $t;
		}
		if ($debug) echo '('.$i.'):('.$t.')<br>';
	}
	return $o;
}

function aa_prog($url,$n) {
	for ($i=0;$i<$n;$i++) $url = dirname($url);
	return $url;
}

function aa_prug($url,$n) {
	$o = "";
	for ($i=0;$i<$n;$i++) {
		$o = substr($url,strlen(dirname($url))).$o;
		$url = dirname($url);
	}
	return $o;
}

	function oh_box_open($type) {
		global $oh;

		if (!is_array($oh["boxes"])) {$oh["boxes"] = array();}

		array_push($oh["boxes"],$type);

		switch($type) {
			// Frame: 
			case "frame":
				return '<div style="'
					 . 'background:#FEFFB3;'		
					 . 'color:#700;'		
					 . 'width:100%;'		
					 . 'border:1px solid #CECF8E;'		
					 . 'font-family:monospace;'		
					 . 'font-size:14px;'		
					 . 'margin-bottom:1px;'		
					 . '">'
					 . '<div style="'
					 . 'margin:5px 5px 5px 5px;'		
					 . '">';

			case "code":
				return '<div style="'
					 . 'color:#333;'		
					 . 'font-family:monospace;'		
					 . 'font-size:12px;'		
					 . 'border:1px solid #d2d2d2;'		
					 . 'background:#fefeff;'		
					 . 'margin:2px 0px 0px 0px;'		
					 . 'padding:4px;'							 
					 . '">';

			case "pre":
				return '<pre style="'
					 . 'color:#222;'		
					 . 'font-family:monospace;'		
					 . 'font-size:12px;'		
					 . 'border:1px solid #d2d2d2;'		
					 . 'background:#dfdfdf;'		
					 . 'margin:2px 0px 0px 0px;'		
					 . 'padding:4px;'							 
					 . '">';

			case "result":
				return '<div style="'
					 . 'color:#000;'		
					 . 'font-family:serif;'		
					 . 'font-size:14px;'		
					 . 'border:2px solid #000;'		
					 . 'background:#fff;'		
					 . 'margin:2px 0px 0px 0px;'		
					 . 'padding:8px;'							 
					 . '">';
			case "small":
				return '<div style="'
					 . 'font-size:10px;'					
					 . 'color:#555;'		
					 . '">';

			case "title":
				return '<div style="'
					 . 'font-family:roman;'					
					 . 'font-size:22px;'	
					 . 'font-weight:bold;'						 				
					 . 'color:#4F4F4A;'		
					 . 'border-bottom:1px solid #dddddd;'							 
					 . 'margin:0px 0px 4px 0px;'							 
					 . '">';

			case "comment":
				return '<div style="'
					 . 'font-family:roman;'					
					 . 'font-size:14px;'	
					 . 'font-style:italic;'	
					 . 'color:#000;'		
					 . '">';

			case "inportant":
				return '<div style="'
					 . 'font-size:15px;'	
					 . 'color:#000;'		
					 . 'background:#FFFFcF;'
					 . 'padding:4px 6px 4px 6px;'
					 . 'border:1px solid #dddddd;'							 
					 . '">';
	
		}
	}
	
		
	function oh_box_close() {
		global $oh;
		
		$type = array_pop($oh["boxes"]);
		
		switch($type) {			
			case "frame":			
				return '</div>'
					 . '</div>';
					 
			case "code":
			  	return '</div>';

			case "pre":
			  	return '</pre>';

			case "result":
			  	return '</div>';
		
			case "small":
			  	return '</div>';

			case "title":
			  	return '</div>';

			case "comment":
			  	return '</div>';

			case "inportant":
			  	return '</div>';

		}		
	}

/*\
 *	oh.codes.includes.php
 *	---------------------
 *
 *
 *
\*/

function oh_code_test($title,$description,$code) {
	echo oh_box_open("frame");
		echo oh_box_open("title");
			echo $title;
		echo oh_box_close();			
		
		echo oh_box_open("comment");
			echo $description;
		echo oh_box_close();			

		echo '<br>Code:';	
		oh_code_print($code);

		echo '<br>Result:';	
		echo oh_box_open("result");
			eval($code);
		echo oh_box_close();			

	echo oh_box_close();
}

function oh_code_print($code) {
	echo oh_box_open("code");
		highlight_string('<?php '."\n".$code."\n".'?>');
	echo oh_box_close();
}

/*\
 *
 *
 *
 *
\*/

# error messages
define("OH_EM000","[000] Warning! No valid function: ");
define("OH_EM001","[001] Warning! No valid actor: ");
define("OH_EM002","[002] Warning! Datasource not found: ");
define("OH_EM004","[004] Warning! Set permission 777 to: ");
define("OH_EM100","[100] Error! Module not found in query: ");
define("OH_EM101","[101] Error! Main function not found in module: ");
define("OH_EM102","[102] Error! Main class not found in module: ");

# html tags
define("br","<br/>");

/*\
 *
 *
 *
 *
\*/

function oh_debug_div_open() {
   return '<div style="'
		. 'background:#ccc;'		
		. 'color:#700;'		
		. 'width:100%;'		
		. 'border:1px solid #777;'		
		. 'font-family:monospace;'		
		. 'font-size:14px;'		
		. 'margin-bottom:1px;'		
		. '">'
		. '<div style="'
		. 'margin:2px 5px 2px 5px;'		
		. '">';
}

function oh_debug_div_close() {
   return '</div>'
		. '</div>';
}

function oh_debug_small_open() {
   return '<div style="'
		. 'font-size:10px;'					
		. 'color:#555;'		
		. '">';
}

function oh_debug_small_close() {
   return '</div>';
}

function oh_debug_pre_open() {
   return '<pre style="'
		. 'color:#333;'		
		. 'font-family:monospace;'		
		. 'font-size:12px;'		
		. 'border:1px solid #aaa;'		
		. 'background:#f1f1f1;'		
		. 'margin:2px 0px 0px 0px;'		
		. 'padding:4px;'		
		. '">';
}

function oh_debug_pre_close() {
   return '</pre>';
}

function oh_dump($o,$t="") {
	echo oh_box_open("frame");	
		if ($t) {
			echo $t; 
		} else {
			echo '$'.oh_var_name($o);
		}			
		echo oh_box_open("small");	
			echo oh_debug_at("oh_dump");			
		echo oh_box_close();		
		echo oh_box_open("pre");	
			var_dump($o);
		echo oh_box_close();
	echo oh_box_close();
}
	
function oh_dump_server() {
	echo '<pre>';
	var_dump($_SERVER);
	echo '</pre>';
}
	
function oh_code($code) {
	echo oh_debug_div_open();
	highlight_string('<?php '."\n".$code."\n".'?>');
	echo oh_debug_div_close();
}
	
function oh_message($msg,$stop = "oh") {
	$stopline = oh_debug_at($stop);
	echo oh_box_open("frame");				
		if ($stopline) {
			echo $msg;
			echo oh_box_open("small");				
				echo $stopline;					
			echo oh_box_close();		
		} else {
			echo oh_box_open("inportant");				
			echo $msg;
		
		}
	echo oh_box_close();
}

function oh_debug_at($stop = "oh") {
	$bt = debug_backtrace();
	foreach($bt as $k=>$v) {
		if (strtolower($v['function']) == $stop) {
			return 'in "'.$v['file'].'" at line '.$v['line'];
		}
	}	
}

/*\
 *
 *
 *
 *
\*/

function oh_strong($string) {
	return '<strong>'.$string.'</strong>';
}

function oh_div($string) {
	return '<div>'.$string.'</div>';
}


/*\
 *
 *
 *
 *
 *
\*/

class oh_info {
	public $info;
	function oh_info($m) {
		$this->info = $m;
	}
	function info() {
		oh_dump($this->info);
	}
	function help() {
		$m = get_class_methods($this->info['class']);
		echo oh_box_open("frame");
			foreach($m as $method) {
				echo oh_div($method);
			}
		echo oh_box_close();
	}
	function dump() {
		oh_dump(oh_this());
	}
	function version() {
		return '0.0.0';
	}
	function is_ready() {
	
	}
}



/*\
 *
\*/
$oh['script'] = dirname($_SERVER['SCRIPT_FILENAME']);

/*\
 *	oh.main.include.php
 *	-------------------
 *
 *
 *
\*/

# main function of the framework
function oh($q = "kernel") {			
	global $oh;
	
	$m = oh_module_parse($q);
	
	if (function_exists($m->function)) {		
		oh_module_default($m);
		return oh_module_call($m);
		
	} else {
		if (oh_module_require($m)) {
			if (class_exists($m->class)) {
				oh_module_init($m);
				
			} else {
				oh_message(OH_EM102.oh_strong($m->name));
				
			}
			if (function_exists($m->function)) {
				return oh_module_call($m);
				
			} else {
				oh_message(OH_EM101.oh_strong($m->name));
				
			}				
		} else {
			oh_message(OH_EM100.oh_strong($m->name));
			
		}	
	}
}


/*\
 *	file: oh.module.php
 *	-------------------
 *
 *
 *
\*/

function &oh_module_parse($query) {
	global $oh;
	
	$i = oh_query_parse($query);

	$m = new stdClass;
	
	$m->name 		= $i['module'];
	$m->token 		= $i['tokens'];
	$m->have 		= count($i['tokens']);
	$m->payload 	= $i['payload'];
	$m->interface	= "oh.".$i['module'].'.interface.php';			
	$m->class	 	= "oh_class_".$i['module'];
	$m->function 	= "oh_function_".$i['module'];	
	$m->object 		= "oh_object_".$i['module'];

	return $m;
}

function oh_module_default(&$m) {
	global ${$m->object};
	if (!isset(${$m->object})) {
		$m->access = "created by default";
		${$m->object} = new stdClass();
		${$m->object}->info = new oh_info($m);
	} else {
		$m->access = "already created";	
	}
}

function oh_module_call(&$m) {
	global $oh;
	$oh['module'][] = $m->name;
	$f = $m->function;
	$r = $f($m);
	return $r;	
}

function oh_module_require(&$m) {
	$p = oh_pack_get_all();
	foreach($p as $pack) {
		$f = $pack.'/'.$m->name.'/'.$m->interface;
		if (file_exists($f)) {
			require_once($f);
			$m->file = $f;		
			return true;
		}	
	}		
	return false;
}





function oh_module_exists($m) {	
	$i = oh_module_interface_file($m);
	if (file_exists($i)) return true;	
	$p = oh_module_packs();
	foreach($p as $pack) {
		$i = oh_module_interface_file($m,$pack);
		if (file_exists($i)) return true;
	}	
	return false;
}




function oh_module_init($m) {
	global ${$m->object};
	${$m->object} = new $m->class();
	${$m->object}->info = new oh_info($m);
}



function &oh_this($o=null) {
	global $oh;

	$d = debug_backtrace();			
	$f = basename($d[0]["file"]);		
	$m = false;
	
	oh_dump($f);
	
	if (!$m) {
		$m = oh_module_get_by_filename($f);
	}
	if (!$m) {
		$m = oh_module_last_in_stack();
	}
	if ($m) {
		global ${"oh_object_".$m};
		if ($o!==null) {
			${"oh_object_".$m} = $o;
		}
		return ${"oh_object_".$m};		
	} else {
		oh_message(EM200);
	}
}

function oh_module_get_by_filename($f) {
	$f = explode(".",$f);
	if ($f[1]=="interface") {
		return $f[0];
	}
	return null;
}

function oh_module_last_in_stack() {
	global $oh;
	return $oh['module'][count($oh['module'])-1];
}


function oh_underscore($name) {
	return str_replace("-","_",$name);
}



function oh_math_integer_divide($x, $y) {
	if ($x == 0) return 0;
	if ($y == 0) return FALSE;
	return ($x - ($x % $y)) / $y;
}

function oh_name_sanitize($textname) {
	$name = $textname;
	$name = trim(strtolower($name));
	$name = str_replace(" ","-",$name);
	return $name;
}

function oh_is_name($textname) {
	if (preg_match("/^[a-zA-Z-0-9]+$/i",$textname)) {
		return true;
	} else {
		return false;	
	}
}

function oh_module_interface_file($modulename,$pack="") {
	global $oh;
	
	if ($pack) {
		return $oh['path'].'/modules/'.$pack.'/'.$modulename.'/'.$modulename.'.interface.php';		
	} else {
		return $oh['path'].'/modules/'.$modulename.'/'.$modulename.'.interface.php';	
	}
}

function oh_framework_is_installed() {
	global $oh;
	return is_dir($oh['path']."/includes");
}

		
function oh_var_name($var) {
    foreach($GLOBALS as $var_name => $value) {
        if ($value === $var) {
            return $var_name;
        }
    }	
    return false;
}


function oh_properties($s) {
	$o = array();
	$s = preg_replace("/[ \t\r\n]+/","",$s);
	$s = explode(",",$s);		
	foreach($s as $i) {
		$i = explode(":",$i);
		$o[$i[0]] = $i[1];
	}
	return $o;
}



/*\
 *	oh.other.include.php
 *	--------------------
 *
 *
 *
\*/

function oh_any($array,$selector="") {
	return in_array($selector,$array) ? $selector : $array[0];
}

function oh_get($index,$array) {
	return isset($_GET[$index])&&in_array($_GET[$index],$array) ? $_GET[$index] : $array[0];
}

function oh_is_valid_function($s) {
	if (preg_match("/^[a-z_][a-z0-9_]*$/i",$s)) {
		if (function_exists($s)) {
			return true;
		}
	} else {
		return false;
	}
	return false;
}

function oh_methods($module = "") {
	if ($module == "") {
		$f = get_defined_functions();
		$f = $f["user"];
		$o = array();
		foreach($f as $i) {
			if (substr($i,0,3) == "oh_") {
				$o[] = $i;
			}
		}
		asort($o);
		return $o;
	} else {
		oh($module);
		$f = get_class_methods("oh_class_".$module);
		asort($f);
		return $f;
	}
}	

function oh_string_to_array($s) {
	$s = explode("," , $s);
	$o = array();
	foreach($s as $i) {
		$i = explode("=>",$i);
		$o[trim($i[0])] = trim($i[1]);
	}
	return $o;
}

function oh_module_header($config="") {
	
}

function oh_get_file_permission($file) {
	return substr(sprintf('%o', fileperms($file)), -4);				
}		

function oh_wellcome() {
	return '
		<style type="text/css">
			body {margin:0;padding:0;}
			#h1	 {padding:10px;background:#507AAA;color:#fff;font-family:Arial,Helvetica,sans-serif;}
		</style>
		<div id="h1"><small>Wellcome to </small>oh.framework</div>
	';
}

function oh_datasource_find($modules) {
	foreach($modules as $module) {
		if (oh("debug.modules.model"))
			oh_message("Test module '{$module}' to find 'model datasource'");
		
		if (oh_module_exists($module)) {
			if (oh($module)->is_ready()) {
				return $module;
			}
		}
	}
	oh_message(OH_EM002.implode(", ",$modules));
	return null;
}

function oh_implode_key($s,$array,$key) {
	$o = array();		
	foreach($array as $item) {
		if (isset($item->$key)) {
			$o[] = $item->$key;
		} else if (isset($item[$key])) {
			$o[] = $item[$key];
		}
	}
	return implode($s,$o);
}	

function oh_stop() {
	die();
}


/*\
 *	file: oh.packs.php
 *	------------------
 *
 *
\*/

function oh_pack_get_all() {
	global $oh;
	
	$oh['packs'] = array();
	$oh['packs'][] = $oh['path']."/modules";
	$oh['packs'][] = $oh['script']."/modules";	
	$ds = scandir($oh['path']."/modules");		
	foreach($ds as $d) {
		if ($d{0} == "_") {
			$oh['packs'][] = $oh['path']."/modules/".$d;
		}
	}
	
	return $oh['packs'];	
}

function oh_pack_add($pack) {
	global $oh;

	$oh['packs'][] = $pack;										
}



function oh_query_parse($query) {		
	$i = array();
	$i['query'] = $query;
	if (strpos($query,":")!==FALSE) {
		$i['command'] = substr($query,0,strpos($query,":"));
		$i['payload'] = substr($query,strpos($query,":")+1);
	} else {
		$i['command'] = $query;
		$i['payload'] = "";	
	}
	if (strpos($i['command'],".")===FALSE) {
		$i['command'] = str_replace("_",".",$i['command']);
	} else {
		# nothing
	}
	$i['tokens'] = explode(".",$i['command']);
	$i['module'] = strtolower($i['tokens'][0]);
	return $i;
}

/*\
 *	oh.token.include.php
 *	--------------------
 *
 *
 *
\*/

function oh_tokens_implode($tokens) {
	$tokens = implode(".",$tokens);
	return $tokens;
}

function oh_tokens_explode($tokens) {
	$tokens = explode(".",$tokens);
	return $tokens;		
}

function oh_tokens_last($tokens) {
	return $tokens[count($tokens)-1];
}

function oh_tokens_implode_slice($tokens,$s) {
	return implode(".",array_slice($tokens,$s));
}

function oh_tokens($tokens) {
	return explode(".",$tokens);
}



/*\
 *	oh.track.include.php
 *	--------------------
 *
 *
 *
\*/

function oh_track_log($filename) {
	global $oh;
	$oh['track'] = array();
	$oh['track']['active'] = true;
	$oh['track']['filename'] = $filename;
	$header = ""
			. ""
			. ""
			. "starting at: ".time()."\n"
			. "-------------------------------------------------------------------\n";		
	file_put_contents($filename,$header);
}

function oh_track_function() {
	oh_track_save();
}

function oh_track_method() {
	oh_track_save();	
}

function oh_track_save($string="") {
	global $oh;
	if (isset($oh['track'])) {
		$line = '[".date("G:i:s")."] oh("'.$string.'")';
		file_put_contents($oh['track']['filename'],$line,FILE_APPEND);
	}	
}

function oh_track_dump() {
	global $oh;
	echo '<pre>';
	echo file_get_contents($oh['track']['filename']);
	echo '</pre>';
}
